package com.come4loves.game.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.come4loves.core.comunicate.codec.ServerDecoderCrypt;
import com.come4loves.core.comunicate.codec.ServerEncoder;
import com.come4loves.core.context.SpringContext;
import com.come4loves.game.server.handler.GatewayHandler;

/**
 * 网关服务器socket服务器启动类
 * 
 * @author ludd
 *
 */
public class GatewaySocketServer {
	private static final Logger LOGGER = LoggerFactory.getLogger(GatewaySocketServer.class);
	public static Boolean tcpNoDelay = (Boolean) SpringContext.getBean("socket.cfg.tcp.nodelay");
	public static Integer backLog = (Integer) SpringContext.getBean("socket.cfg.backlog");
	public static Integer bothIdleTime = (Integer) SpringContext.getBean("socket.cfg.both.idle.time");
	private static GatewaySocketServer instance = new GatewaySocketServer();

	private ServerBootstrap b = new ServerBootstrap();

	private EventLoopGroup bossGroup;
	private EventLoopGroup workerGroup;

	private SslContext sslCtx;

	private GatewaySocketServer() {

		bossGroup = new NioEventLoopGroup();
		workerGroup = new NioEventLoopGroup();

		try {

			b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					if (sslCtx != null) {
						ch.pipeline().addLast(sslCtx.newHandler(ch.alloc()));
					}
					ch.pipeline().addLast(new IdleStateHandler(bothIdleTime, bothIdleTime, bothIdleTime, TimeUnit.SECONDS), new ServerDecoderCrypt(), new ServerEncoder(), new GatewayHandler());
				}
			}).option(ChannelOption.SO_BACKLOG, backLog).childOption(ChannelOption.SO_KEEPALIVE, true).childOption(ChannelOption.TCP_NODELAY, tcpNoDelay);

		} catch (Exception e) {
			LOGGER.error("gateway server", e);
		}
	}

	/**
	 * 启动
	 */
	public void start() {
		try {
			// Bind and start to accept incoming connections.
			final int port = (int) SpringContext.getBean("socket.cfg.server.port");
			ChannelFuture f = b.bind(port).sync();
			f.addListener(new ChannelFutureListener() {

				@Override
				public void operationComplete(ChannelFuture future) throws Exception {
					LOGGER.info("gateway start complete! server socket bind in :{}", port);

				}
			});
			f.channel().closeFuture().sync();
		} catch (Exception ex) {
			LOGGER.error("gateway server", ex);
			System.exit(0);
		}

	}

	public void stop() {
		LOGGER.info("stopping gateway server");
		if (workerGroup != null && bossGroup != null) {
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}

	public static GatewaySocketServer getInstance() {
		return instance;
	}

}
